package edu.hawaii.halealohacli.command;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.sensordata.jaxb.SensorData;
import org.wattdepot.resource.source.jaxb.Source;

/**
 * Gets the energy data of a source since a given date.
 * 
 * @author Group BackR
 * 
 */
public class EnergySince implements Command {

  private String command = "energy-since";
  private String arguments = "[tower | lounge] [date]";
  private int numParams = 2;
  private String help = "Returns the energy used since the date (yyyy-mm-dd) to now.";

  @Override
  public String run(String[] input, WattDepotClient client) {
    double energy = 0;
    String output = "\"" + input[1] + "\" is not a valid source.";
    try {
      List<Source> sources = client.getSources();
      for (Source source : sources) {
        if (source.getName().equals(input[1])) {
          // Create a date format to check the date of the second argument.
          String formatString = "yyyy-MM-dd";
          SimpleDateFormat format = new SimpleDateFormat(formatString, Locale.US);
          format.setLenient(false);
          // Check if second argument is a valid date.
          Date date = format.parse(input[2]);
          // New date format to include in the output.
          SimpleDateFormat checkTime = new SimpleDateFormat("MMM-dd-yyyy 'at' HH:mm:ss", Locale.US);
          GregorianCalendar gc = new GregorianCalendar();
          DatatypeFactory dtf = DatatypeFactory.newInstance();
          XMLGregorianCalendar today = dtf.newXMLGregorianCalendar(gc);
          // Set the date to the user input.
          gc.setTime(date);
          // Create the specified day start.
          XMLGregorianCalendar specifiedDayStart = dtf.newXMLGregorianCalendar(gc);
          // Checks if input date is a future date.
          if (today.compare(specifiedDayStart) < 0) {
            // New date format to include in output if date is a future date.
            SimpleDateFormat futureDate = new SimpleDateFormat("MMM-dd-yyyy", Locale.US);
            output =
                "You have entered a future date: " + futureDate.format(gc.getTime()) + "\n"
                    + "It will be impossible to gather the data, don't you think? Try again.";
          }
          // Check if given date is the current date. A case if a user accesses the data of the
          // current day at midnight.
          else if (today.compare(specifiedDayStart) == 0) {
            output = "The given date is today's date. Currently new data is being recieve until "
                + "12:01AM\nYou can access this data in a minute or try again and enter a date "
                + "before today's date.";
          }
          else {
            // Set time to zero.
            specifiedDayStart.setTime(0, 0, 0, 0);
            // Get the latest sensor data.
            SensorData data = client.getLatestSensorData(source.getName());
            // Get the time stamp of the latest sensor data.
            XMLGregorianCalendar currentDay = data.getTimestamp();
            // Get the energy consumed
            energy = client.getEnergyConsumed(input[1], specifiedDayStart, currentDay, 10);
            energy = energy / 1000;
            GregorianCalendar gcToday = new GregorianCalendar();
            // Create decimal format for the energy data by including one decimal place.
            DecimalFormat dFormat = new DecimalFormat("####.0");
            output =
                input[1] + "'s energy consumption from " + checkTime.format(gc.getTime()) + " to "
                    + checkTime.format(gcToday.getTime()) + " was " + dFormat.format(energy)
                    + " kWh";
          }
        }
      }
    }
    catch (NotAuthorizedException e) {
      return "Unauthorized to access the sever. Try again.";
    }
    catch (BadXmlException e) {
      return "Could not retrieve data for: " + input[1] + " on " + input[2] + "\n"
          + "It might be possible that the date entered is too back in the past. Try again.";
    }
    catch (MiscClientException e) {
      return "Unexpected error. Try again.";
    }
    catch (ResourceNotFoundException e) {
      return input[1] + " does not exist!";
    }
    catch (DatatypeConfigurationException e) {
      return "Could not format date input.";
    }
    catch (ParseException e) {
      return "\"" + input[2] + "\" is not a valid date.";
    }
    catch (IllegalArgumentException e) {
      return "\"" + input[2] + "\" is not a valid date.";
    }
    return output;
  }

  @Override
  public String getCommand() {
    return command;
  }

  @Override
  public int getNumParams() {
    return numParams;
  }

  @Override
  public String getHelp() {
    return command + " " + arguments + "\n" + help;
  }

}
